﻿#include "media_source/vcm_capturer.h"

#include <rtc_base/logging.h>
#include <rtc_base/task_utils/to_queued_task.h>
#include <modules/video_capture/video_capture_factory.h>

#include "xrtc/ixrtc_engine.h"
#include "base/xrtc_global.h"

namespace xrtc {

VcmCapturer* VcmCapturer::Create(size_t width, size_t height, size_t fps, 
    const std::string& device_id) 
{
    VcmCapturer* vcm_capturer = new VcmCapturer(width, height, fps, device_id);
    if (!vcm_capturer->Init(width, height, fps, device_id)) {
        return nullptr;
    }
    return vcm_capturer;
}

VcmCapturer::VcmCapturer(size_t width, size_t height, size_t fps,
    const std::string& device_id) :
    current_thread_(rtc::Thread::Current()),
    width_(width),
    height_(height),
    fps_(fps),
    device_id_(device_id)
{
}

bool VcmCapturer::Init(size_t width, size_t height, size_t fps, 
    const std::string& device_id) 
{
    vcm_ = webrtc::VideoCaptureFactory::Create(device_id.c_str());
    if (!vcm_) {
        RTC_LOG(LS_WARNING) << "failed to create vcm capturer, device_id: "
            << device_id;
        return false;
    }

    vcm_->RegisterCaptureDataCallback(this);

    std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> device_info(
        webrtc::VideoCaptureFactory::CreateDeviceInfo());
    device_info->GetCapability(vcm_->CurrentDeviceName(), 0, capability_);

    capability_.width = width;
    capability_.height = height;
    capability_.maxFPS = fps;
    capability_.videoType = webrtc::VideoType::kI420;

    return true;
}

void VcmCapturer::Destroy() {
    if (!vcm_) {
        return;
    }

    vcm_->StopCapture();
    vcm_->DeRegisterCaptureDataCallback();
    vcm_ = nullptr;
}

VcmCapturer::~VcmCapturer() {
    Destroy();
}

bool VcmCapturer::Start() {
    current_thread_->PostTask(webrtc::ToQueuedTask([=]() {
        XRTCError err = XRTCError::kNoErr;
        do {
            if (!vcm_) {
                RTC_LOG(LS_WARNING) << "vcm not init";
                err = XRTCError::kVideoSourceNotInit;
                break;
            }

            if (vcm_->StartCapture(capability_) != 0) {
                RTC_LOG(LS_WARNING) << "start capture failed, device_id: " << vcm_->CurrentDeviceName();
                Destroy();
                err = XRTCError::kVideoSourceStartErr;
                break;
            }

            RTC_LOG(LS_INFO) << "video capturer started: " << vcm_->CaptureStarted();
        
        } while (false);

        // 统一错误处理
        XRTCEngineObserver* observer = XRTCGlobal::Instance()->engine_observer();
        if (observer) {
            observer->OnVideoSourceStartEvent(this, err);
        }

    }));

    return true;
}

void VcmCapturer::Stop() {
    current_thread_->PostTask(webrtc::ToQueuedTask([=]() {
        if (vcm_) {
            vcm_->StopCapture();
        }

        XRTCEngineObserver* observer = XRTCGlobal::Instance()->engine_observer();
        if (observer) {
            observer->OnVideoSourceStopEvent(this, XRTCError::kNoErr);
        }
    }));
}

void VcmCapturer::OnFrame(const webrtc::VideoFrame& frame) {
    // 可以获得摄像头的采集数据
    current_thread_->PostTask(webrtc::ToQueuedTask([=]() {
        broadcaster_.OnFrame(frame);
    }));
}

void VcmCapturer::AddOrUpdateSink(
    VideoSinkInterface<webrtc::VideoFrame>* sink, 
    const rtc::VideoSinkWants& wants) 
{
    current_thread_->PostTask(webrtc::ToQueuedTask([=]() {
        broadcaster_.AddOrUpdateSink(sink, wants);
    }));
}

void VcmCapturer::RemoveSink(VideoSinkInterface<webrtc::VideoFrame>* sink) 
{
    current_thread_->PostTask(webrtc::ToQueuedTask([=]() {
        broadcaster_.RemoveSink(sink);
    }));
}

} // namespace xrtc